package DataStructure.QueueLearning.QueueLinked;

public class LinkedQueue <E> {
    // 定义队列长度
    private int size;
    // 定义头尾指针
    private Node head;
    private Node tail;

    /**
     *  在队尾添加新元素
     * @param e 添加的元素
     * @return 返回成功与否
     */
    public boolean offer(E e) {
        // 判断传入元素是否为空，是则报错
        if(e == null) {
            throw new IllegalArgumentException("The parame is null");
        }
        // 创建新节点
        Node node = new Node(e, null);
        // 如果原本队列为空，则将头尾指针置为新节点
        if(size == 0) {
            head = node;
            tail = node;
            size++;
            return true;
        }
        // 如果队列不为空，则将原本最后的节点指向新节点，尾指针指向新节点
        tail.next = node;
        tail = node;
        size++;
        return true;
    }

    /**
     *  删除队头元素
     * @return 返回被删除的元素
     */
    public E poll() {
        // 如果队列为空，返回空值
        if(size == 0) {
            return null;
        }
        // 将第一个元素的内容保存
        E oldValue = head.value;
        // 如果队列只有一个节点，则将头尾指针置空，长度减一
        if(size == 1) {
            head = null;
            tail = null;
            size--;
            return oldValue;
        }
        // 如果队列不止一个节点，则将头指针后移，长度减一
        head = head.next;
        size--;
        return oldValue;
    }

    /**
     *  判断队列是否为空
     * @return 返回boolean
     */
    public boolean isEmpty() {
        // 如果长度为0，返回true；否则false
        return size == 0;
    }

    /**
     *  给出队列中元素个数
     * @return 返回个数
     */
    public int size() {
        // 返回长度
        return size;
    }

    /**
     *  查看队头元素
     * @return 返回队头元素
     */
    public E peek() {
        // 返回队头节点内容
        return head.value;
    }

    @Override
    public String toString() {
        return "{" +
                "head=" + head +
                ", size=" + size +
                '}';
    }

    // 定义内部类节点
    class Node {
        E value;
        Node next;

        public Node(E value, Node next) {
            this.value = value;
            this.next = next;
        }

        @Override
        public String toString() {
            return "{" +
                    "v=" + value +
                    ", n=" + next +
                    '}';
        }
    }
}
